package com.spzx.cart.service.impl;

import com.spzx.cart.api.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.vo.SkuPrice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements ICartService {

    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    RemoteProductService remoteProductService;
    public String getCartKey(Long userId){
        return "cart:" + userId;
    }
// 添加购物车
    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        // 获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();
        //1.构建“用户”购物车hash结构key  user：用户ID：cart
        String cartKey = getCartKey(userId);
        //2.创建Hash结构绑定操作对象（方便对hash进行操作）
        BoundHashOperations<String,String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        //4.判断用户购物车中是否包含该商品 如果包含：数量进行累加(某件商品数量上限99) 不包含：新增购物车商品
        CartInfo cartInfo = boundHashOperations.get(skuId.toString());
        Integer threshold = 99;
        if (cartInfo != null) {
            //4.1 说明该商品在购物车中已有，对数量进行累加 ，不能超过指定上限99
           Integer cartNum= cartInfo.getSkuNum() + skuNum;
           cartInfo.setSkuNum(cartNum>threshold?threshold:cartNum);
           boundHashOperations.put(skuId.toString(),cartInfo);
        }else {
            //3.判断购物车商品种类（不同SKU）总数大于50件
            Long size = boundHashOperations.size();
            if (size >= 49){
                throw new RuntimeException("商品种类数量超过上限！");
            }else {
                //4. 说明购物车没有该商品，构建购物车对象，存入Redis
                cartInfo = new CartInfo();
                cartInfo.setUserId(userId);
                cartInfo.setSkuId(skuId);
                cartInfo.setSkuNum(skuNum>threshold?threshold:skuNum);
                cartInfo.setUpdateTime(new Date());
                cartInfo.setCreateTime(new Date());
                //4.1 远程调用商品服务获取商品sku基本信息
                R<ProductSku> productSku = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
                if (R.FAIL == productSku.getCode()){
                    throw new RuntimeException(productSku.getMsg());
                }else{
                    ProductSku data = productSku.getData();//商品sku信息
                    cartInfo.setSkuName(data.getSkuName());
                    cartInfo.setThumbImg(data.getThumbImg());
                    R<SkuPrice> skuPrice = remoteProductService.getSkuPrice(skuId, SecurityConstants.INNER);
                    if (R.FAIL == skuPrice.getCode()) {
                        throw new RuntimeException(skuPrice.getMsg());
                    }else {
                        //4.2 远程调用商品服务获取商品实时价格
                        SkuPrice data1 = skuPrice.getData();
                        cartInfo.setCartPrice(data1.getSalePrice());
                        cartInfo.setSkuPrice(data1.getSalePrice());
                        //4.3 将购物车商品存入Redis
                       boundHashOperations.put(skuId.toString(),cartInfo);
                    }
                }
            }
        }
    }

    @Override
    public List<CartInfo> cartList() {
        // 获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);//绑定hash结构
        // 获取数据
        List<CartInfo> cartInfoList = boundHashOperations.values();
        if (!CollectionUtils.isEmpty(cartInfoList))//集合不为空
        {
            List<Long> list = cartInfoList.stream().map(CartInfo::getSkuId).toList();//获取skuId,集合
            R<List<SkuPrice>> skuPriceList = remoteProductService.getSkuPriceList(list, SecurityConstants.INNER);//远程调用商品服务批量获取商品实时价格
            if (R.FAIL == skuPriceList.getCode()){
                throw new ServiceException(skuPriceList.getMsg());
            }
            List<SkuPrice> data = skuPriceList.getData();//商品实时价格
            Map<Long, BigDecimal> skuIdToPriceMap = data.stream().collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
            for (CartInfo cartInfo : cartInfoList) {
                cartInfo.setSkuPrice(skuIdToPriceMap.get(cartInfo.getSkuId()));
            }
            return cartInfoList;

        }else {
            return new ArrayList<>();
        }
    }

    @Override
    public void deleteCart(Long skuId) {
        Long userId = SecurityContextHolder.getUserId();//通过线程获取用户id
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        boundHashOperations.delete(skuId.toString());
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        if (boundHashOperations.hasKey(skuId.toString())){
            CartInfo cartInfo = boundHashOperations.get(skuId.toString());
            cartInfo.setIsChecked(isChecked);
            boundHashOperations.put(skuId.toString(),cartInfo);
        }else{
            throw new RuntimeException("购物车没有此商品！");
        }
    }

    @Override
    public void allCheckCart(Integer isChecked) {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);//绑定hash结构
        List<CartInfo> values = boundHashOperations.values();
        for (CartInfo value : values) {
            CartInfo cartInfo = boundHashOperations.get(value.getSkuId().toString());//获取购物车商品
            cartInfo.setIsChecked(isChecked);
            boundHashOperations.put(value.getSkuId().toString(),cartInfo);
        }
    }

    @Override
    public void clearCart() {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = this.getCartKey(userId);
        redisTemplate.delete(cartKey);
    }

    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        List<CartInfo> cartInfoList = new ArrayList<>();
        String cartKey = this.getCartKey(userId);
        List<CartInfo> values = redisTemplate.opsForHash().values(cartKey);
        if (!CollectionUtils.isEmpty(values)){
            for (CartInfo cartInfo : values) {
                if (cartInfo.getIsChecked() == 1){
                    cartInfoList.add(cartInfo);
                }
            }
        }
        return cartInfoList;
    }

    @Override
    public Boolean updateCartPrice(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = boundHashOperations.values();
        if (!CollectionUtils.isEmpty(cartInfoList)){
            for (CartInfo cartInfo : cartInfoList) {
                R<SkuPrice> skuPrice = remoteProductService.getSkuPrice(cartInfo.getSkuId(), SecurityConstants.INNER);
                if (R.FAIL == skuPrice.getCode()){
                    throw new ServiceException(skuPrice.getMsg());
                }
                SkuPrice skuPricenew = skuPrice.getData();
                cartInfo.setCartPrice(skuPricenew.getSalePrice());
                cartInfo.setSkuPrice(skuPricenew.getSalePrice());
                boundHashOperations.put(cartInfo.getSkuId().toString(),cartInfo);
            }
        }
        return true;
    }

    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = boundHashOperations.values();
        if (!CollectionUtils.isEmpty(cartInfoList)){
            for (CartInfo cartInfo : cartInfoList) {
                if (cartInfo.getIsChecked() == 1){
                    boundHashOperations.delete(cartInfo.getSkuId().toString());
                }
            }
        }
        return true;
    }
}